#pragma once
#include "Session.hpp" // 引入 session
#include "TcpServer.hpp"
#include <ctime>
#include <functional>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include<string.h>

const std::string HttpSep = "\r\n";
// 可以配置的
const std::string homepage = "index.html";
const std::string wwwroot = "./wwwroot";

class HttpRequest 
{
public:
  HttpRequest() : _req_blank(HttpSep), _path(wwwroot) {}
  bool GetLine(std::string &str, std::string *line) 
  {
    auto pos = str.find(HttpSep);
    if (pos == std::string::npos)
      return false;
    *line = str.substr(0, pos); // \r\n
     str.erase(0, pos + HttpSep.size());
    return true;
  }

  void Parse() 
  {
    // 解析出来 url
    std::stringstream ss(_req_line);
    ss >> _method >> _url >> _http_version;
    // 查找 cookie
    std::string prefix = "Cookie: ";
    for (auto &line : _req_header) 
    {
      std::string cookie;
      if (strncmp(line.c_str(), prefix.c_str(),
                  prefix.size()) == 0) // 找到了
      {
        cookie = line.substr(prefix.size()); // 截取"Cookie: "之后的就行了
         _cookies.emplace_back(cookie);
        break;
      }
    }
    // 查找 sessionid
    prefix = "sessionid=";
    for (const auto &cookie : _cookies) {
      if (strncmp(cookie.c_str(), prefix.c_str(), prefix.size()) == 0) 
      {
        _sessionid = cookie.substr(prefix.size()); // 截取"sessionid="之后的就行了
            // std::cout << "_sessionid: " << _sessionid <<std::endl;
      }
    }
  }
  std::string Url() { return _url; }
  std::string SessionId() { return _sessionid; }
  bool Deserialize(std::string &request) {
    std::string line;
    bool ok = GetLine(request, &line);
    if (!ok)
      return false;
    _req_line = line;
    while (true) {
      bool ok = GetLine(request, &line);
      if (ok && line.empty()) {
        _req_content = request;
        break;
      } else if (ok && !line.empty()) {
        _req_header.push_back(line);
      } else {
        break;
      }
    }
    return true;
  }
  void DebugHttp() {
    std::cout << "_req_line: " << _req_line << std::endl;
    for (auto &line : _req_header) {
      std::cout << "---> " << line << std::endl;
    }
  }
  ~HttpRequest() {}

private:
      // http 报文自动
        std::string _req_line; // method url http_version
        std::vector<std::string> _req_header;
        std::string _req_blank;
        std::string _req_content;
        // 解析之后的内容
        std::string _method;
        std::string _url; // / /dira/dirb/x.html
//   / dira / dirb / XX ? usrname = 100 &&password =
//                            1234 / dira / dirb std::string _http_version;
        std::string _path;                 // "./wwwroot"
        std::string _suffix;               // 请求资源的后缀
        std::vector<std::string> _cookies; // 其实 cookie 可以有多个，因为 Set - Cookie 可以被写多条，测试，一条够了。
        std::string _sessionid; // 请求携带的 sessionid，仅仅用来测试
};

const std::string BlankSep = " ";
const std::string LineSep = "\r\n";

class HttpResponse 
{
public:
  HttpResponse()
      : _http_version("HTTP/1.0"), _status_code(200), _status_code_desc("OK"),
        _resp_blank(LineSep) {}
  void SetCode(int code) { _status_code = code; }
  void SetDesc(const std::string &desc) { _status_code_desc = desc; }
  void MakeStatusLine() 
  {
    _status_line = _http_version + BlankSep + std::to_string(_status_code) +
                   BlankSep + _status_code_desc + LineSep;
  }
  void AddHeader(const std::string &header) 
   {
        _resp_header.push_back(header + LineSep);
   }
  void AddContent(const std::string &content) { _resp_content = content; }
  std::string Serialize() {
    MakeStatusLine();
    std::string response_str = _status_line;
    for (auto &header : _resp_header) {
      response_str += header;
    }
    response_str += _resp_blank;
    response_str += _resp_content;
    return response_str;
  }
  ~HttpResponse() {}

private:
  std::string _status_line;
  std::vector<std::string> _resp_header;
  std::string _resp_blank;
  std::string _resp_content; // body
  // httpversion StatusCode StatusCodeDesc
  std::string _http_version;
  int _status_code;
  std::string _status_code_desc;
};

